/*
 * Copyright (c) 2010, German Buela
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * The name of German Buela may not be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY GERMAN BUELA "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL GERMAN BUELA BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.gbuela.winco.system

import com.gbuela.winco.model._

sealed trait OS
case object Windows extends OS
case object Unix extends OS

class DriveMapping(val id:String, val mapping:Map[OS,String]) 

trait WincoConfig 
{
  val os:OS 

  val player: String
  val collections: List[Musicollection]
  val drives: List[DriveMapping] 
  val remDrives: List[DriveMapping]
  
  def resolvePath(path:String):String = {
    if(path startsWith "$")
    {
      val driveMapping = (drives find { m => path.substring(1) startsWith m.id }).get
      val physDrive = driveMapping.mapping(os)
      physDrive + (path substring (driveMapping.id.length + 2))
    }
    else
    {
      path
    }
  }
}

trait OSDetection
{
  val getOS:OS = if(System.getProperty("os.name").toUpperCase.indexOf("WINDOWS") > -1) Windows else Unix
}

class Config(val xmlDoc:xml.Elem, val os:OS) extends WincoConfig
{
  import xml._
  
  private val rootTag = "config"
  private val playerTag = "player"
  private val drivesTag = "drives"
  private val driveTag = "drive"
  private val idAtt = "id"
  private val winAtt = "win"
  private val unixAtt = "unix"
  private val collectionsTag = "collections"
  private val collectionTag = "collection"
  private val nameTag = "name"
  private val locationTag = "location"
  private val remDrivesTag = "removable-drives"
  private val audioExtensionsTag = "audioExtensions"
  private val audioExtTag = "audioExt"
  
  private lazy val data = readData()

  private def xmlDriveToMapping(d:Node):DriveMapping = {
    val id = d.attribute(idAtt).get.toString
    val winDrive = d.attribute(winAtt).get.toString
    val unixDrive = d.attribute(unixAtt).get.toString
    new DriveMapping(id, Map[OS,String](Windows -> winDrive, Unix -> unixDrive))
  }
  
  private def xmlToMusicollection(exts: List[String])(d:Node):Musicollection = {
    val name = (d\\nameTag).text
    val location = (d\\locationTag).text
    new Musicollection(name, location, resolvePath, exts)
  }
  
  private def readData():Map[String,Any] = {
    import xml._

    val cfgPlayer = xmlDoc\\rootTag\\playerTag

    val cfgDrives = xmlDoc\\drivesTag\\driveTag
    val drives:List[DriveMapping] = cfgDrives.toList map xmlDriveToMapping
    
    val cfgRemDrives = xmlDoc\\remDrivesTag\\driveTag
    val remDrives:List[DriveMapping] = cfgRemDrives.toList map xmlDriveToMapping
  
    val cfgExtensions = xmlDoc\\audioExtensionsTag\\audioExtTag
    val exts: List[String] = cfgExtensions.toList map (_.text)
        
    val cfgCollections = xmlDoc\\collectionsTag\\collectionTag
    val colls:List[Musicollection] = cfgCollections.toList map xmlToMusicollection(exts)

    Map[String,Any]("player" -> cfgPlayer.text, 
                    "drives" -> drives,
                    "colls" -> colls, 
                    "remdrs" -> remDrives)
  }
  
  lazy val player = data("player").asInstanceOf[String]
  lazy val collections = data("colls").asInstanceOf[List[Musicollection]]
  lazy val drives = data("drives").asInstanceOf[List[DriveMapping]]
  lazy val remDrives = data("remdrs").asInstanceOf[List[DriveMapping]]  
}


